﻿#define _CRT_SECURE_NO_WARNINGS 1
// 原题连接：https://ac.nowcoder.com/acm/problem/229386
/*
题目描述：
链接：https://ac.nowcoder.com/acm/problem/229386
来源：牛客网

dd作为体操队队长，在给队员们排队形，体操队形为一个单独的纵列，体操队有
𝑛
n个同学，标号为
1
∼
𝑛
1∼n，对于
𝑖
(
1
≤
𝑖
≤
𝑛
)
i(1≤i≤n)号队员，会有一个诉求
(
1
≤
𝑎
[
𝑖
]
≤
𝑛
)
(1≤a[i]≤n)，表示他想排在
𝑎
[
𝑖
]
a[i]号队员前面，当
𝑎
[
𝑖
]
=
𝑖
a[i]=i时，我们认为他没有位置需求，随便排哪儿都行，
𝑑
𝑑
dd想知道有多少种队形方案，可以满足所有队员的要求。
输入描述:
读入第一行一个数字n(2≤n≤10)
第二行n个数字，表示a[i],保证1≤a[i]≤n
输出描述:
输出一行，表示方案数
示例1
输入
复制
3
1 1 2
输出
复制
1
*/


// 开始解题：
// 方法——dfs
#include <iostream>
#include <cstring>
using namespace std;
const int N = 15;
int n = 0;
int nums[N];
bool vis[N];
int ret = 0;

void dfs(int pos) {
    if (pos == n + 1) {
        ret++;
        return;
    }
    for (int i = 1; i <= n; i++) {
        if (i == nums[i] && !vis[i]) {
            // 随便放
            vis[i] = true;
            dfs(pos + 1);
            vis[i] = false;
        }
        else {
            if (!vis[i]) {
                if (!vis[nums[i]]) {
                    // pos要放在nums[pos]前面，所以如果nums[pos]就不能被放过
                    vis[i] = true;
                    dfs(pos + 1);
                    vis[i] = false;
                }
                else {
                    // 如果nums[i]已经被放过了，那么不管后面怎么放，i都不可能放到nums[i]的前面
                    // 所以直接返回
                    return;
                }
            }
        }
    }
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &nums[i]);
    }
    dfs(1);
    cout << ret << endl;
    return 0;
}